// libvln.h

#pragma once

#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>

typedef unsigned long long u_int64;
typedef long long int64;
typedef unsigned int u_int32;
typedef unsigned char byte;

#define byteLength sizeof(u_int32)
#define LIMIT 1000000000

namespace irontree {

	namespace libvln {

		class Cvln
		{
			bool signBit;
			u_int64 itemCount;
			u_int32* itemPool;
		public:

			
			Cvln() : itemCount(0), itemPool(NULL), signBit(false)
			{
				// initilize itemPool, and itemCount
				// allocates memory and sets count value
				resize(1);
			}
			Cvln(const Cvln &a) : itemPool(NULL), itemCount(0), signBit(false)
			{
				// same as default constructor
				resize(1);
				// borrow copy method from assignment overload
				operator=(a);
			}
			Cvln(const u_int64 &a) : itemPool(NULL), itemCount(0), signBit(false)
			{
				resize(1);
				u_int64 pos = 0;
				u_int64 num = a;
				u_int32 low = 0;
				while ( num >= LIMIT )
				{
					low = num % LIMIT;
					setItem(pos, low);
					num = (num - low) / LIMIT;
					++pos;
				}
				setItem(pos, (u_int32)num);
			}

			~Cvln() 
			{
				// release memory allocated by resize()
				free(itemPool);
			}

			// resize() takes length in units, converts to bytes
			void resize(const u_int64 &length);
			bool setSign(bool setTo) { return signBit = setTo; }
			bool getSign() { return signBit; }

			u_int64 Count() 
				{ return itemCount; }

			void shiftLeft(u_int64 distance);
			void setItem(const u_int64 &index, const u_int32 &value);
			std::string toString();
			static Cvln power(const Cvln &base, const Cvln &exponent);
			static u_int64 BinaryAddition(u_int32 lhs, u_int32 rhs);

			Cvln firstBig(u_int64 number = 1);
			Cvln& operator=(const Cvln &rhs);
			u_int32 operator[](const u_int64 &index);

			friend bool operator==(const Cvln &left, const Cvln &right);
			friend bool operator!=(const Cvln &left, const Cvln &right);
			friend bool operator<(const Cvln &left, const Cvln &right);
			friend bool operator<=(const Cvln &left, const Cvln &right);
			friend bool operator>(const Cvln &left, const Cvln &right);
			friend bool operator>=(const Cvln &left, const Cvln &right);
			friend Cvln operator+(const Cvln &left, const Cvln &right);
			friend Cvln operator-(const Cvln &left, const Cvln &right);
			friend Cvln operator*(const Cvln &left, const Cvln &right);

		};
	}
}
